package ro.ubbcluj.cs.damate.plugin.amq;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import ro.ubbcluj.cs.damate.plugin.DamateActivator;
import ro.ubbcluj.cs.damate.plugin.events.PluginEvent;
import ro.ubbcluj.cs.damate.plugin.services.AuthenticationService;
import ro.ubbcluj.cs.damate.plugin.utils.DamateLogger;
import ro.ubbcluj.cs.damate.plugin.ws.service.WebServiceClient;

import javax.annotation.Resource;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
import javax.jms.Session;

@Service
public class PluginEventConsumer implements MessageListener {

    @Autowired
    private DamateLogger log;

    @Autowired
    @Qualifier("consumerJmsTemplate")
    private JmsTemplate template;

    @Resource
    private Destination destination;

    @Autowired
    @Qualifier("pluginEventMessageSelector")
    private String messageSelectorId;
    
    @Autowired
    private WebServiceClient webServiceClient;

    private AuthenticationService authenticationService;

    private Connection connection;
    private Session session;
    private MessageConsumer consumer;

    public void start() {
        String selector = "messageSelector = '" + messageSelectorId + "'";

        try {
            ConnectionFactory factory = template.getConnectionFactory();
            connection = factory.createConnection();

            synchronized (connection) {
                if (connection.getClientID() == null) {
                    connection.setClientID(messageSelectorId+"Connection");
                }
            }

            connection.start();

            session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);
            consumer = session.createConsumer(destination, selector, false);
            consumer.setMessageListener(this);
        } catch (JMSException ex) {
            log.error("An error occurred while trying to start the plugin event consumer: " + ex.getMessage(), ex);
        }
    }

    public void stop() throws JMSException {
        if (consumer != null) {
            consumer.close();
        }
        if (session != null) {
            session.close();
        }
        if (connection != null) {
            connection.close();
        }
    }

    public void onMessage(Message message) {
        try {
            if (getAuthenticationService().isAuthenticated()) {
                PluginEvent event = (PluginEvent) ((ObjectMessage)message).getObject();
                log.info("Processing event message from the queue: " + event);
                if (webServiceClient.sendPluginEvent(event, getAuthenticationService().getAuthenticationToken()) == 200) {
                    message.acknowledge();
                }
            }
        } catch (JMSException e) {
            log.error("Failed to acknowledge: " + e.getMessage(), e);
        }
    }

    public AuthenticationService getAuthenticationService() {
        if (authenticationService == null) {
            this.authenticationService = DamateActivator.getDefault().getAuthenticationService();
        }
        return authenticationService;
    }
}
